package com.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.mall.config.MyPayConfig;
import com.mall.dao.OrderItemMapper;
import com.mall.dao.OrderMapper;
import com.mall.dao.ProductSkuMapper;
import com.mall.dao.ShoppingCartVOMapper;
import com.mall.entity.*;
import com.mall.service.OrderService;
import com.mall.vo.ResultVO;
import com.mall.service.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private ShoppingCartVOMapper shoppingCartVOMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    @Transactional
    @Override
    public Map<String,String> addOrder(String[] cids, Orders order) {
        HashMap<String, String> map = new HashMap<>();
        ArrayList<Integer> cidsList = new ArrayList<>();
        for (int i=0;i<cids.length;i++){
            cidsList.add(Integer.parseInt(cids[i]));
        }
        List<ShoppingCartVO> shoppingCartVOS = shoppingCartVOMapper.selectShopcartByCids(cidsList);
        String untitled="";
        Boolean isBuy=true;
        for (int i=0;i<shoppingCartVOS.size();i++){
            if (Integer.parseInt(shoppingCartVOS.get(i).getCartNum())>=shoppingCartVOS.get(i).getStock()){
                isBuy=false;
            }
           if (i!=shoppingCartVOS.size()-1) {
               untitled = shoppingCartVOS.get(i).getProductName() + ",";
           }
        }
            if (isBuy){
                order.setUntitled(untitled);
                order.setCreateTime(new Date());
                order.setUpdateTime(new Date());
                String orderId = UUID.randomUUID().toString().replace("-", "");
                order.setOrderId(orderId);
                order.setStatus(1+"");
                order.setDeleteStatus(0);
                int i = orderMapper.insert(order);
                //生成商品快照
                Double total_amount=null;
                for (ShoppingCartVO shoppingCartVO:shoppingCartVOS){
                    OrderItem orderItem = new OrderItem();
                    String itemId = System.currentTimeMillis()+""+ (new
                            Random().nextInt(89999)+10000);
                    Integer cartNum = Integer.parseInt(shoppingCartVO.getCartNum());
                    total_amount=shoppingCartVO.getSellPrice()*cartNum;
                  //  int i = shoppingCartVO.getProductPrice() * cartNum;
                    orderItem.setItemId(itemId)
                            .setOrderId(orderId)
                            .setProductId(shoppingCartVO.getProductId())
                            .setProductName(shoppingCartVO.getProductName())
                            .setProductImg(shoppingCartVO.getProductImg())
                            .setSkuId(shoppingCartVO.getSkuId())
                            .setSkuName(shoppingCartVO.getSkuName())
                            .setProductPrice(new BigDecimal(shoppingCartVO.getSellPrice()))
                            .setBuyCounts(cartNum)
                            .setTotalAmount(new BigDecimal(total_amount))
                            .setBasketDate(new Date())
                            .setBuyTime(new Date())
                            .setIsComment(0);
                    int i2 = orderItemMapper.insert(orderItem);
                }
                 //4.扣减库存：根据套餐ID修改套餐库存量
                for (ShoppingCartVO shoppingCartVO:shoppingCartVOS){
                    ProductSku productSku = new ProductSku();
                    int stock=shoppingCartVO.getStock() - Integer.parseInt(shoppingCartVO.getCartNum());
                    productSku.setSkuId(shoppingCartVO.getSkuId()).setStock(stock).setUpdateTime(new Date());
                    productSkuMapper.updateById(productSku);
                }
                //5.删除购物⻋：当购物⻋中的记录购买成功之后，购物⻋中对应做删除操作
                for (Integer cid:cidsList){
                    shoppingCartVOMapper.deleteById(cid);
                }
                map.put("orderId",orderId);
                map.put("productNames",untitled);
                map.put("total_amount",total_amount+"");
                return map;
            }
        return null;
    }

    public ResultVO getWXPay(Map<String,String> orderInfo) {
        //6.获得到订单id和商品名称后，需要请求微信支付接口，生成二维码
     /*   String orderId="123123124324";*/
        HashMap<String, String> map2 = new HashMap<>();
        map2.put("body",orderInfo.get("productNames"));//商品描述
        map2.put("out_trade_no", orderInfo.get("orderId"));//使用当前用户订单的编号作为当前支付交易的交易号
        map2.put("fee_type", "CNY");//支付币种
        map2.put("total_fee",(Integer.parseInt(orderInfo.get("total_amount"))*100)+""); //支付金额
        map2.put("trade_type","NATIVE");//交易类型
        map2.put("notify_url","http://203.25.223.57:8080/pay/callback"); //回调地址
        //to do...
        MyPayConfig myPayConfig = new MyPayConfig();
        WXPay wxPay = new WXPay(myPayConfig);
        try {
            Map<String, String> resp = wxPay.unifiedOrder(map2);
            orderInfo.put("payUrl",resp.get("code_url"));
            return ResultVO.success("订单保存成功！",orderInfo);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultVO.fail("生成支付二维码失败！");
        }
    }

    @Override
    public String callback(HttpServletRequest request) throws Exception {
        ServletInputStream is = request.getInputStream();
        byte[] bytes = new byte[1024];
        StringBuilder builder = new StringBuilder();
        int len=-1;
        while ((len=is.read())!=-1){
            builder.append(new String(bytes));
        }
        //使用帮助类将xml接口的字符串转换成map
        Map<String, String> map = WXPayUtil.xmlToMap(builder.toString());
        if (map!=null && "success".equalsIgnoreCase(map.get("result_code"))){
            //支付成功
            //1.修改订单状态
            Orders order = new Orders();
            String orderId=map.get("out_trade_no");
            order.setOrderId(orderId);
            Integer i = updateOrderStatus(order);
            //需要通过websocket通知前端，用户已付款
            WebSocketServer.sendMsg(orderId, "1");
            if (i>0){
                //2.需要响应微信支付平台，不然微信会一直推送消息
                HashMap<String, String> resp = new HashMap<>();
                resp.put("return_code","success");
                resp.put("return_msg", "OK");
                resp.put("appid", map.get("appid"));
                resp.put("result_code", "success");
                return WXPayUtil.mapToXml(resp);
            }
        }
        return null;
    }

    @Override
    public ResultVO getOrderById(String orderId) {
        Orders order = orderMapper.selectById(orderId);
        return ResultVO.success(order.getStatus());
    }
    @Transactional(isolation = Isolation.SERIALIZABLE) //设置事务的隔离级别是串行话
    @Override
    public void closeOrder(String orderId) {
        Orders closeOrder = new Orders();
        closeOrder.setOrderId(orderId).setStatus("6").setCloseType(1).setUpdateTime(new Date());
        orderMapper.updateById(closeOrder);
        System.out.println("==========");
        //3.还原库存，先根据当前订单编号查询商品快照
        QueryWrapper<OrderItem> query2 = new QueryWrapper<>();
        query2.eq("order_id", orderId);
        List<OrderItem> orderItems = orderItemMapper.selectList(query2);
        synchronized (this){
            for (int j=0;j<orderItems.size();j++){
                String skuId = orderItems.get(j).getSkuId();
                Integer buyCount = orderItems.get(j).getBuyCounts();
                ProductSku productSku = productSkuMapper.selectById(skuId);
                //还原库存
                productSku.setStock(productSku.getStock()+buyCount);
                productSkuMapper.updateById(productSku);
            }
        }

    }

    @Override
    public Integer updateOrderStatus(Orders order) {
        order.setPayTime(new Date()).setUpdateTime(new Date()).setStatus(2+"");
        return orderMapper.updateById(order);
    }
}
